package GUI;

import Biblioteca.*;
import Player.*;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.Timer;
import javazoom.jlgui.basicplayer.BasicPlayer;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextPane;
import javax.swing.ListCellRenderer;

/**
 *
 * @author IS G2
 */
public class PlayerWindow extends javax.swing.JFrame {

    private Player player;
    private ListaReproduccion lista;
    private LectorTags lector;
    private EditorTagsWindow editor;
    private BibliotecaWindow biblioteca;
    /**
     * Guarda el estado actual del botón repeat: 0 = desactivado, 1 = repeatOne, 2 = repeatALL
     */
    private int estadoRepetir = 0;
    private boolean aleatorio = false;
    /**
     * Alterna entre tiempo que lleva y tiempo restante en el label del tiempo
     */
    private boolean tiempoRestante = false;
    private boolean actualizarTiempoTrasSalto = false;
    private int valorBarraProgreso = 0;
    private double tiempoCancionActual = 0;
    /**
     * Se ejecuta 1 vez cada segundo actualizando la barra de progreso y el label del tiempo
     */
    private Timer timer = new Timer(1000, new ActionListener() {

        public void actionPerformed(ActionEvent e) {
            progressBar.setValue(valorBarraProgreso);
            if (actualizarTiempoTrasSalto) {
                tiempoCancionActual = (float) progressBar.getValue() / (float) progressBar.getMaximum() * Double.parseDouble(player.getCancionPlayer().getTag("duracion"));
                actualizarTiempoTrasSalto = false;
            } else {
                tiempoCancionActual++;
            }
            if (tiempoRestante) {
                String tiempoTotal = player.getCancionPlayer().getTag("duracion");
                if (tiempoTotal.equals("Desconocido")) {
                    tiempoLabel.setText("??:??");
                } else {
                    double tiempo = Double.parseDouble(tiempoTotal) - tiempoCancionActual;
                    if (tiempo > 0) {
                        tiempoLabel.setText("-" + formatTime(tiempo));
                    } else {
                        tiempoLabel.setText("-00:00");
                    }
                }
            } else {
                tiempoLabel.setText(formatTime(tiempoCancionActual));
            }
        }
    });

    /**
     * Constructora por defecto
     */
    public PlayerWindow() {
        initComponents();
        player = new Player(this);
        lista = new ListaReproduccion();
        lector = new LectorTags();
        biblioteca = null;
        limpiarInfoCancion();
    }

    /**
     * Constructora con parametro para abrir el reproductor con una cancion cargada
     * @param ruta
     */
    public PlayerWindow(String ruta) {
        initComponents();
        player = new Player(this);
        lista = new ListaReproduccion();
        lector = new LectorTags();
        biblioteca = null;
        if (ruta.toLowerCase().endsWith(".mp3")) {
            aniadirCancion(ruta);
            playButtonActionPerformed(null);
        } else {
            JOptionPane.showMessageDialog(this, "No estas introduciendo un archivo de audio compatible", "ERROR", JOptionPane.ERROR_MESSAGE);
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        songListModel = new javax.swing.DefaultListModel();
        songListPopUp = new javax.swing.JPopupMenu();
        anadirBibOpt = new javax.swing.JMenuItem();
        editTagOpt = new javax.swing.JMenuItem();
        eliminarOpt = new javax.swing.JMenuItem();
        playButton = new javax.swing.JButton();
        pauseButton = new javax.swing.JButton();
        addSongButton = new javax.swing.JButton();
        stopButton = new javax.swing.JButton();
        deleteSongButton = new javax.swing.JButton();
        tiempoLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();
        nextButton = new javax.swing.JButton();
        prevButton = new javax.swing.JButton();
        volumenSlider = new javax.swing.JSlider();
        repeatButton = new javax.swing.JButton();
        bibliotecaButton = new javax.swing.JButton();
        randomButton = new javax.swing.JButton();
        helpButton = new javax.swing.JButton();
        scrollPanel = new javax.swing.JScrollPane();
        songLabel = new javax.swing.JTextPane();
        songLabel.setContentType("text/html");
        saveListButton = new javax.swing.JButton();
        loadListButton = new javax.swing.JButton();
        scrollPane2 = new javax.swing.JScrollPane();
        songListArea = new javax.swing.JList();

        anadirBibOpt.setText("Añadir a Biblioteca");
        anadirBibOpt.setToolTipText("Añade la cancion seleccionada a la Biblioteca");
        anadirBibOpt.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                anadirBibOptActionPerformed(evt);
            }
        });
        songListPopUp.add(anadirBibOpt);

        editTagOpt.setText("Editar Tags ");
        editTagOpt.setToolTipText("Edita los tags del archivo mp3");
        editTagOpt.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editTagOptActionPerformed(evt);
            }
        });
        songListPopUp.add(editTagOpt);

        eliminarOpt.setText("Eliminar Canción");
        eliminarOpt.setToolTipText("Elimina la canción de la lista de reproducción.");
        eliminarOpt.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                eliminarOptActionPerformed(evt);
            }
        });
        songListPopUp.add(eliminarOpt);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("DHMO");
        setBackground(new java.awt.Color(102, 102, 102));
        setForeground(new java.awt.Color(240, 240, 240));
        setMinimumSize(new java.awt.Dimension(345, 240));
        setName("DHMO Player"); // NOI18N
        addMouseWheelListener(new java.awt.event.MouseWheelListener() {
            public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
                formMouseWheelMoved(evt);
            }
        });
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
        });

        playButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_play.png"))); // NOI18N
        playButton.setMnemonic('x');
        playButton.setBorder(null);
        playButton.setContentAreaFilled(false);
        playButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_play_pressed.png"))); // NOI18N
        playButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playButtonActionPerformed(evt);
            }
        });

        pauseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_pause.png"))); // NOI18N
        pauseButton.setMnemonic('c');
        pauseButton.setBorder(null);
        pauseButton.setContentAreaFilled(false);
        pauseButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_pause_pressed.png"))); // NOI18N
        pauseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pauseButtonActionPerformed(evt);
            }
        });

        addSongButton.setFont(new java.awt.Font("Trebuchet MS", 0, 10));
        addSongButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/addsong_button.png"))); // NOI18N
        addSongButton.setMnemonic('A');
        addSongButton.setToolTipText("Añadir canción");
        addSongButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/addsong_button_pressed.png"))); // NOI18N
        addSongButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addSongButtonActionPerformed(evt);
            }
        });

        stopButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_stop.png"))); // NOI18N
        stopButton.setMnemonic('z');
        stopButton.setBorder(null);
        stopButton.setContentAreaFilled(false);
        stopButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_stop_pressed.png"))); // NOI18N
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });

        deleteSongButton.setFont(new java.awt.Font("Trebuchet MS", 0, 10));
        deleteSongButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/erasesong_button.png"))); // NOI18N
        deleteSongButton.setMnemonic('B');
        deleteSongButton.setToolTipText("Borrar cancion");
        deleteSongButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/erasesong_button_pressed.png"))); // NOI18N
        deleteSongButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteSongButtonActionPerformed(evt);
            }
        });

        tiempoLabel.setFont(new java.awt.Font("Verdana", 1, 18)); // NOI18N
        tiempoLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        tiempoLabel.setText("00:00");
        tiempoLabel.setFocusable(false);
        tiempoLabel.setMaximumSize(new java.awt.Dimension(91, 24));
        tiempoLabel.setMinimumSize(new java.awt.Dimension(91, 24));
        tiempoLabel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                tiempoLabelMousePressed(evt);
            }
        });

        progressBar.setFocusable(false);
        progressBar.setMaximumSize(new java.awt.Dimension(293, 14));
        progressBar.setMinimumSize(new java.awt.Dimension(293, 14));
        progressBar.setPreferredSize(new java.awt.Dimension(293, 14));
        progressBar.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                progressBarMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                progressBarMouseReleased(evt);
            }
        });

        nextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_next.png"))); // NOI18N
        nextButton.setMnemonic('v');
        nextButton.setBorder(null);
        nextButton.setContentAreaFilled(false);
        nextButton.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        nextButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_next_pressed.png"))); // NOI18N
        nextButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextButtonActionPerformed(evt);
            }
        });

        prevButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_prev.png"))); // NOI18N
        prevButton.setMnemonic('<');
        prevButton.setBorder(null);
        prevButton.setContentAreaFilled(false);
        prevButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/button_prev_pressed.png"))); // NOI18N
        prevButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                prevButtonActionPerformed(evt);
            }
        });

        volumenSlider.setValue(100);
        volumenSlider.setMaximumSize(new java.awt.Dimension(91, 24));
        volumenSlider.setMinimumSize(new java.awt.Dimension(91, 24));
        volumenSlider.setPreferredSize(new java.awt.Dimension(91, 24));
        volumenSlider.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                volumenSliderMousePressed(evt);
            }
        });
        volumenSlider.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                volumenSliderMouseDragged(evt);
            }
        });

        repeatButton.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        repeatButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/repeat_off.png"))); // NOI18N
        repeatButton.setToolTipText("Repetir desactivado");
        repeatButton.setMaximumSize(new java.awt.Dimension(23, 24));
        repeatButton.setMinimumSize(new java.awt.Dimension(23, 24));
        repeatButton.setPreferredSize(new java.awt.Dimension(23, 24));
        repeatButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                repeatButtonActionPerformed(evt);
            }
        });

        bibliotecaButton.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        bibliotecaButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/lib_button.png"))); // NOI18N
        bibliotecaButton.setToolTipText("Abrir Biblioteca de Música");
        bibliotecaButton.setMaximumSize(new java.awt.Dimension(23, 24));
        bibliotecaButton.setMinimumSize(new java.awt.Dimension(23, 24));
        bibliotecaButton.setPreferredSize(new java.awt.Dimension(23, 24));
        bibliotecaButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/lib_button_pressed.png"))); // NOI18N
        bibliotecaButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bibliotecaButtonActionPerformed(evt);
            }
        });

        randomButton.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        randomButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/random_off.png"))); // NOI18N
        randomButton.setToolTipText("Reproducción Secuencial");
        randomButton.setMaximumSize(new java.awt.Dimension(23, 24));
        randomButton.setMinimumSize(new java.awt.Dimension(23, 24));
        randomButton.setPreferredSize(new java.awt.Dimension(23, 24));
        randomButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/random_off_pressed.png"))); // NOI18N
        randomButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                randomButtonActionPerformed(evt);
            }
        });

        helpButton.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        helpButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/help_button.png"))); // NOI18N
        helpButton.setToolTipText("Ayuda");
        helpButton.setMaximumSize(new java.awt.Dimension(23, 24));
        helpButton.setMinimumSize(new java.awt.Dimension(23, 24));
        helpButton.setPreferredSize(new java.awt.Dimension(23, 24));
        helpButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/help_button_pressed.png"))); // NOI18N
        helpButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                helpButtonActionPerformed(evt);
            }
        });

        scrollPanel.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPanel.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        scrollPanel.setFocusable(false);
        scrollPanel.setMaximumSize(new java.awt.Dimension(325, 93));
        scrollPanel.setMinimumSize(new java.awt.Dimension(325, 93));
        scrollPanel.setPreferredSize(new java.awt.Dimension(325, 93));
        scrollPanel.setRequestFocusEnabled(false);

        songLabel.setEditable(false);
        songLabel.setFont(new java.awt.Font("Verdana", 0, 14));
        songLabel.setForeground(new java.awt.Color(150, 207, 250));
        songLabel.setAutoscrolls(false);
        songLabel.setFocusable(false);
        songLabel.setMaximumSize(new java.awt.Dimension(293, 61));
        songLabel.setMinimumSize(new java.awt.Dimension(293, 61));
        songLabel.setPreferredSize(new java.awt.Dimension(293, 61));
        songLabel.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
            public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
                songLabelMouseWheelMoved(evt);
            }
        });
        scrollPanel.setViewportView(songLabel);
        songLabel.getAccessibleContext().setAccessibleDescription("text/html");

        saveListButton.setFont(new java.awt.Font("Trebuchet MS", 0, 10));
        saveListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/savelist_button.png"))); // NOI18N
        saveListButton.setMnemonic('g');
        saveListButton.setToolTipText("Guardar lista");
        saveListButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/savelist_button_pressed.png"))); // NOI18N
        saveListButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveListButtonActionPerformed(evt);
            }
        });

        loadListButton.setFont(new java.awt.Font("Trebuchet MS", 0, 10));
        loadListButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/loadlist_button.png"))); // NOI18N
        loadListButton.setMnemonic('c');
        loadListButton.setToolTipText("Cargar lista");
        loadListButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/loadlist_button_pressed.png"))); // NOI18N
        loadListButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadListButtonActionPerformed(evt);
            }
        });

        scrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        songListArea.setModel(songListModel);
        songListArea.setAutoscrolls(false);
        songListArea.setCellRenderer(new HtmlRenderer());
        songListArea.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                songListAreaMouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                songListAreaMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                songListAreaMouseReleased(evt);
            }
        });
        songListArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                songListAreaKeyReleased(evt);
            }
        });
        scrollPane2.setViewportView(songListArea);
        songListArea.getAccessibleContext().setAccessibleDescription("");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(scrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 325, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 325, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(scrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 325, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(addSongButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(deleteSongButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(prevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(stopButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(playButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(pauseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(nextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(saveListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(loadListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(tiempoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(bibliotecaButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(randomButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(repeatButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(helpButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(volumenSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(scrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tiempoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(volumenSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(helpButton, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(repeatButton, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(randomButton, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(bibliotecaButton, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(prevButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(deleteSongButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(addSongButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(stopButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(playButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(pauseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(nextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(saveListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(loadListButton, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(scrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 178, Short.MAX_VALUE)
                .addContainerGap())
        );

        tiempoLabel.getAccessibleContext().setAccessibleName("  00:00");

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-361)/2, (screenSize.height-419)/2, 361, 419);
    }// </editor-fold>//GEN-END:initComponents

    private void addSongButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addSongButtonActionPerformed
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Añadir canción");
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        fc.setMultiSelectionEnabled(true);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Archivo MP3", "mp3");
        fc.addChoosableFileFilter(filter);
        fc.removeChoosableFileFilter(fc.getAcceptAllFileFilter());
        int result = fc.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File[] archivos = fc.getSelectedFiles();
            ArrayList<String> rutas = getRutasRec(archivos);
            for (Iterator it = rutas.iterator(); it.hasNext();) {
                String ruta = (String) it.next();
                if (ruta.toLowerCase().endsWith(".mp3")) {
                    aniadirCancion(ruta);
                }
            }
        }
    }//GEN-LAST:event_addSongButtonActionPerformed

    private void deleteSongButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteSongButtonActionPerformed
        int seleccion[] = songListArea.getSelectedIndices();
        for (int i = seleccion.length - 1; i >= 0; i--) {
            if (seleccion[i] >= 0) {
                songListModel.remove(seleccion[i]);
                lista.eliminarCancion(seleccion[i]);
                songListArea.ensureIndexIsVisible(seleccion[i]);
                songListArea.setSelectedIndex(seleccion[i]);
            }
        }
    }//GEN-LAST:event_deleteSongButtonActionPerformed

    private void prevButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevButtonActionPerformed
        Cancion cancion = lista.cancionAnterior();
        songListArea.ensureIndexIsVisible(songListModel.indexOf(cancion));
        if (lista.cancionActual() != null) {
            player.stop();
            timer.stop();
            timer.restart();
            pintarInfoCancion(lista.cancionActual());
            songListArea.repaint();
            player.play(cancion);
            reiniciaProgressBar();
            timer.start();
        } else {
            timer.stop();
            player.stop();
            reiniciaProgressBar();
            limpiarInfoCancion();
        }
    }//GEN-LAST:event_prevButtonActionPerformed

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed
        if (player.getCancionPlayer() != null) {
            timer.stop();
            player.stop();
            reiniciaProgressBar();
            songListArea.repaint();
            limpiarInfoCancion();
        }
    }//GEN-LAST:event_stopButtonActionPerformed

    private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed
        if (player.getEstado() == BasicPlayer.PAUSED) {
            timer.start();
            player.resume();
        } else {
            int seleccion = songListArea.getSelectedIndex();
            songListArea.repaint();
            if (seleccion != -1) {
                timer.stop();
                Cancion cancion = lista.saltarACancionSeleccionada(seleccion);
                pintarInfoCancion(lista.cancionActual());
                player.play(cancion);
                reiniciaProgressBar();
                timer.start();
            } else if (lista.cancionActual() != null) {
                timer.stop();
                Cancion cancion = lista.cancionActual();
                pintarInfoCancion(lista.cancionActual());
                player.play(cancion);
                reiniciaProgressBar();
                timer.start();
            } else {
                timer.stop();
                player.stop();
                reiniciaProgressBar();
                limpiarInfoCancion();
            }
        }
    }//GEN-LAST:event_playButtonActionPerformed

    private void pauseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseButtonActionPerformed
        if (player.getCancionPlayer() != null) {
            if (player.getEstado() == BasicPlayer.PLAYING) {
                timer.stop();
                player.pause();
            } else if (player.getEstado() == BasicPlayer.PAUSED) {
                timer.start();
                player.resume();
            }
        }
    }//GEN-LAST:event_pauseButtonActionPerformed

    private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
        Cancion cancion = lista.cancionSiguiente();
        songListArea.ensureIndexIsVisible(songListModel.indexOf(cancion));
        if (cancion != null) {
            player.stop();
            timer.stop();
            timer.restart();
            pintarInfoCancion(lista.cancionActual());
            songListArea.repaint();
            player.play(cancion);
            reiniciaProgressBar();
            timer.start();
        } else {
            timer.stop();
            player.stop();
            reiniciaProgressBar();
            limpiarInfoCancion();
        }
        songListArea.ensureIndexIsVisible(songListModel.indexOf(cancion));
    }//GEN-LAST:event_nextButtonActionPerformed

    private void progressBarMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_progressBarMouseReleased
        if (player.getCancionPlayer() != null) {
            timer.stop();
            tiempoCancionActual = (float) progressBar.getValue() / (float) progressBar.getMaximum() * Double.parseDouble(player.getCancionPlayer().getTag("duracion"));
            if (tiempoRestante) {
                String tiempoTotal = player.getCancionPlayer().getTag("duracion");
                if (tiempoTotal.equals("Desconocido")) {
                    tiempoLabel.setText("??:??");
                } else {
                    tiempoLabel.setText("-" + formatTime(Double.parseDouble(tiempoTotal) - tiempoCancionActual));
                }
            } else {
                tiempoLabel.setText(formatTime(tiempoCancionActual));
            }
            actualizarTiempoTrasSalto = true;
            player.seekByte(progressBar.getValue());
            timer.start();
        }
    }//GEN-LAST:event_progressBarMouseReleased

    private void bibliotecaButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bibliotecaButtonActionPerformed
        if (this.biblioteca == null) {
            this.biblioteca = new BibliotecaWindow(this);
            this.biblioteca.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
            this.biblioteca.setVisible(true);
        } else if (!this.biblioteca.isVisible()) {
            this.biblioteca.setVisible(true);
        }
    }//GEN-LAST:event_bibliotecaButtonActionPerformed

    private void randomButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_randomButtonActionPerformed
        if (aleatorio) {
            randomButton.setIcon(new ImageIcon(getClass().getResource("/images/random_off.png")));
            randomButton.setPressedIcon(new ImageIcon(getClass().getResource("/images/random_off_pressed.png")));
            randomButton.setToolTipText("Reproducción Secuencial");
            lista.secuenciarLista();
            aleatorio = false;
        } else {
            randomButton.setIcon(new ImageIcon(getClass().getResource("/images/random_on.png")));
            randomButton.setPressedIcon(new ImageIcon(getClass().getResource("/images/random_on_pressed.png")));
            randomButton.setToolTipText("Reproducción Aleatoria");
            lista.mezclarListaNueva();
            aleatorio = true;
        }
    }//GEN-LAST:event_randomButtonActionPerformed

    private void repeatButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_repeatButtonActionPerformed
        if (estadoRepetir == 0) {
            repeatButton.setIcon(new ImageIcon(getClass().getResource("/images/repeat_one.png")));
            repeatButton.setToolTipText("Repetir canción actual");
            lista.setRepeatAll(false);
            estadoRepetir = 1;
        } else if (estadoRepetir == 1) {
            repeatButton.setIcon(new ImageIcon(getClass().getResource("/images/repeat_all.png")));
            repeatButton.setToolTipText("Repetir lista de canciones");
            lista.setRepeatAll(true);
            estadoRepetir = 2;
        } else {
            repeatButton.setIcon(new ImageIcon(getClass().getResource("/images/repeat_off.png")));
            repeatButton.setToolTipText("Repetir desactivado");
            lista.setRepeatAll(false);
            estadoRepetir = 0;
        }
    }//GEN-LAST:event_repeatButtonActionPerformed

    private void progressBarMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_progressBarMousePressed
        if (player.getCancionPlayer() != null) {
            timer.stop();
            tiempoCancionActual = (double) ((float) progressBar.getValue() / (float) progressBar.getMaximum() * Double.parseDouble(player.getCancionPlayer().getTag("duracion")));
            progressBar.setValue((int) ((float) evt.getX() / (float) progressBar.getWidth() * (float) progressBar.getMaximum()));
            timer.start();
        }

    }//GEN-LAST:event_progressBarMousePressed

    private void tiempoLabelMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tiempoLabelMousePressed
        if (player.getCancionPlayer() != null) {
            if (tiempoRestante) {
                tiempoRestante = false;
                tiempoLabel.setText(formatTime(tiempoCancionActual));
            } else {
                tiempoRestante = true;
                String tiempoTotal = player.getCancionPlayer().getTag("duracion");
                if (tiempoTotal.equals("Desconocido")) {
                    tiempoLabel.setText("??:??");
                } else {
                    tiempoLabel.setText("-" + formatTime(Double.parseDouble(tiempoTotal) - tiempoCancionActual));
                }
            }
        }
    }//GEN-LAST:event_tiempoLabelMousePressed

    private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
        this.setSize(355, this.getSize().height);
    }//GEN-LAST:event_formComponentResized

    private void volumenSliderMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_volumenSliderMouseDragged
        double volumen = (double) volumenSlider.getValue() / 100;
        if (player.getCancionPlayer() != null) {
            player.changeVolume(volumen);
        } else {
            player.setVolume(volumen);
        }
    }//GEN-LAST:event_volumenSliderMouseDragged

    private void volumenSliderMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_volumenSliderMousePressed
        volumenSlider.setValue(evt.getX());
        double volumen = (double) volumenSlider.getValue() / 100;
        if (player.getCancionPlayer() != null) {
            player.changeVolume(volumen);
        } else {
            player.setVolume(volumen);
        }
    }//GEN-LAST:event_volumenSliderMousePressed

    private void formMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {//GEN-FIRST:event_formMouseWheelMoved
        volumenSlider.setValue(volumenSlider.getValue() - evt.getWheelRotation() * 5);
        double volumen = (double) volumenSlider.getValue() / 100;
        if (player.getCancionPlayer() != null) {
            player.changeVolume(volumen);
        } else {
            player.setVolume(volumen);
        }
    }//GEN-LAST:event_formMouseWheelMoved

    private void songLabelMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {//GEN-FIRST:event_songLabelMouseWheelMoved
        volumenSlider.setValue(volumenSlider.getValue() - evt.getWheelRotation() * 5);
        double volumen = (double) volumenSlider.getValue() / 100;
        if (player.getCancionPlayer() != null) {
            player.changeVolume(volumen);
        } else {
            player.setVolume(volumen);
        }
    }//GEN-LAST:event_songLabelMouseWheelMoved

    private void saveListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveListButtonActionPerformed
        JFileChooser fc = new JFileChooser();
        fc.setDialogType(JFileChooser.SAVE_DIALOG);
        fc.setDialogTitle("Guardar lista");
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Archivo de texto", "txt");
        fc.addChoosableFileFilter(filter);
        fc.removeChoosableFileFilter(fc.getAcceptAllFileFilter());
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int result = fc.showSaveDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            String ruta = fc.getSelectedFile().getAbsolutePath();
            if (!ruta.contains(".txt")) {
                ruta += ".txt";
            }
            File file = new File(ruta);
            if (file.exists()) {
                int result2 = JOptionPane.showConfirmDialog(this, "El archivo seleccionado se sobreescribirá.", "Aviso", JOptionPane.YES_NO_OPTION);
                if (result2 == JOptionPane.NO_OPTION) {
                    return;
                }
            }
            try {
                PrintWriter writer = new PrintWriter(file);
                for (int i = 0; i < lista.tamanio(); i++) {
                    writer.print(lista.dameCancion(i).getRuta() + "\n");
                }
                writer.close();
            } catch (FileNotFoundException ex) {
                Logger.getLogger(PlayerWindow.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_saveListButtonActionPerformed

    private void loadListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadListButtonActionPerformed
        JFileChooser fc = new JFileChooser();
        fc.setDialogType(JFileChooser.OPEN_DIALOG);
        fc.setDialogTitle("Cargar lista");
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Archivo de texto", "txt");
        fc.addChoosableFileFilter(filter);
        fc.removeChoosableFileFilter(fc.getAcceptAllFileFilter());
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fc.setMultiSelectionEnabled(false);
        int result = fc.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            BufferedReader reader = null;
            try {
                lista = new ListaReproduccion();
                songListModel.removeAllElements();
                String ruta = fc.getSelectedFile().getAbsolutePath();
                File file = new File(ruta);
                reader = new BufferedReader(new FileReader(file));
                if (aleatorio) {
                    aleatorio = false;
                    String rutaCancion = reader.readLine();
                    while (rutaCancion != null) {
                        aniadirCancion(rutaCancion);
                        rutaCancion = reader.readLine();
                    }
                    aleatorio = true;
                    lista.mezclarListaNueva();
                } else {
                    String rutaCancion = reader.readLine();
                    while (rutaCancion != null) {
                        aniadirCancion(rutaCancion);
                        rutaCancion = reader.readLine();
                    }
                }
            } catch (IOException ex) {
                Logger.getLogger(PlayerWindow.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_loadListButtonActionPerformed

    private void songListAreaKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_songListAreaKeyReleased
        switch (evt.getKeyCode()) {
            case KeyEvent.VK_DELETE:
                deleteSongButtonActionPerformed(null);
                break;
            case KeyEvent.VK_ENTER:
                playButtonActionPerformed(null);
                break;
        }
    }//GEN-LAST:event_songListAreaKeyReleased

    private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed
        //TODO: revisar, arreglar para que funcione sin seleccionar el volumeSlider, y aumentar velocidad. Incluir tb controles derecha e izqda para saltar x segs en barra progreso?
        if (evt.getKeyCode() == KeyEvent.VK_UP) {
            volumenSlider.setValue(volumenSlider.getValue() + 1);
        } else if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
            volumenSlider.setValue(volumenSlider.getValue() - 1);
        }
        double volumen = (double) volumenSlider.getValue() / 100;
        if (player.getCancionPlayer() != null) {
            player.changeVolume(volumen);
        } else {
            player.setVolume(volumen);
        }
    }//GEN-LAST:event_formKeyPressed

    /**
     * Gestiona los eventos por click del ratón
     * @param e
     */
    public void check(MouseEvent e) {
        int[] seleccion = songListArea.getSelectedIndices();
        if (songListArea.locationToIndex(e.getPoint()) > -1) {
            if (e.isPopupTrigger()) { //if the event shows the menu
                songListArea.setSelectedIndices(seleccion);
                songListPopUp.show(songListArea, e.getX(), e.getY());
            }
        }
    }

    private void eliminarOptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_eliminarOptActionPerformed
        deleteSongButtonActionPerformed(null);
    }//GEN-LAST:event_eliminarOptActionPerformed

    private void editTagOptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editTagOptActionPerformed
        //TODO: actualizar informacion de la lista o la cancion en reproduccion cuando se han editado sus tags
        final int seleccion = songListArea.getSelectedIndex();
        if (seleccion != -1) {
            final Cancion cancion = lista.dameCancion(seleccion);
            editor = new EditorTagsWindow(cancion, this);
            editor.setVisible(true);
        } else {
            JOptionPane.showMessageDialog(this, "No has seleccionado ninguna cancion de la lista!.", "ERROR", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_editTagOptActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        if (this.biblioteca != null) {
            this.biblioteca.cerrando();
        }
    }//GEN-LAST:event_formWindowClosing

    private void anadirBibOptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_anadirBibOptActionPerformed
        // añadir cancion(es)a la biblioteca
        int seleccion[] = songListArea.getSelectedIndices();
        for (int i = seleccion.length - 1; i >= 0; i--) {
            if (seleccion[i] >= 0) {
                File f = new File(((Cancion) songListModel.get(i)).getRuta());
                biblioteca.cargarCancionDeArchivo(f);
            }
        }
    }//GEN-LAST:event_anadirBibOptActionPerformed

    private void songListAreaMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_songListAreaMousePressed
        check(evt);
    }//GEN-LAST:event_songListAreaMousePressed

    private void songListAreaMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_songListAreaMouseReleased
        check(evt);
    }//GEN-LAST:event_songListAreaMouseReleased

    private void songListAreaMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_songListAreaMouseClicked
        if (evt.getClickCount() > 1) {
            playButtonActionPerformed(null);
        }
    }//GEN-LAST:event_songListAreaMouseClicked

    private void helpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_helpButtonActionPerformed
        try {
            String currentDir = System.getProperty("user.dir");
            Desktop.getDesktop().open(new File(currentDir + "\\Manual de usuario DHMO.pdf"));
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(this, "No se encuentra el archivo Manual de usuario DHMO.pdf", "ERROR", JOptionPane.ERROR_MESSAGE);
        }

    }//GEN-LAST:event_helpButtonActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addSongButton;
    private javax.swing.JMenuItem anadirBibOpt;
    private javax.swing.JButton bibliotecaButton;
    private javax.swing.JButton deleteSongButton;
    private javax.swing.JMenuItem editTagOpt;
    private javax.swing.JMenuItem eliminarOpt;
    private javax.swing.JButton helpButton;
    private javax.swing.JButton loadListButton;
    private javax.swing.JButton nextButton;
    private javax.swing.JButton pauseButton;
    private javax.swing.JButton playButton;
    private javax.swing.JButton prevButton;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JButton randomButton;
    private javax.swing.JButton repeatButton;
    private javax.swing.JButton saveListButton;
    private javax.swing.JScrollPane scrollPane2;
    private javax.swing.JScrollPane scrollPanel;
    private javax.swing.JTextPane songLabel;
    private javax.swing.JList songListArea;
    private javax.swing.DefaultListModel songListModel;
    private javax.swing.JPopupMenu songListPopUp;
    private javax.swing.JButton stopButton;
    private javax.swing.JLabel tiempoLabel;
    private javax.swing.JSlider volumenSlider;
    // End of variables declaration//GEN-END:variables

    // METODOS PROPIOS NO ASOCIADOS A EVENTOS NI PARTE DEL GUI
    /**
     * Añade la canción que hay en ruta en la lista de reproducción y en el songList
     * @param ruta contiene la ruta de la canción a añadir
     */
    public void aniadirCancion(String ruta) {
        Cancion cancion = new Cancion(ruta);
        cancion.cargarCancionIndependiente();
        aniadirCancion(cancion);
    }

    /**
     * Añade la canción en la lista de reproducción y en el songList
     * @param cancion contiene la cancion a añadir
     */
    public void aniadirCancion(Cancion cancion) {
        songListModel.addElement(cancion);
        if (aleatorio) {
            lista.aniadirCancionAleatoriamente(cancion);
        } else {
            lista.aniadirCancion(cancion);
        }
    }

    /**
     * Devuelve un arraylist de Strings cuyo contenido son las rutas
     * de los archivos seleccionados y las de los archivos dentro de
     * directorios de forma recursiva.
     * @param archivos
     * @return array de rutas a archivos
     */
    public ArrayList<String> getRutasRec(File[] archivos) {
        ArrayList<String> aux = new ArrayList<String>();
        for (int i = 0; i < archivos.length; i++) {
            if (archivos[i].isDirectory()) {
                aux.addAll(getRutasRec(archivos[i].listFiles()));
            }
            if (archivos[i].isFile()) {
                aux.add(archivos[i].getAbsolutePath());
            }
        }
        return aux;
    }

    /**
     * Método que pinta los datos de la canción en el player cuando se va a reproducir. Admite html para formatear
     * @param cancion
     */
    public void pintarInfoCancion(Cancion cancion) {
        //TODO: cargar archivo caratula real
        String artista = cancion.getArtista().getNombre();
        String titulo = cancion.getTitulo();
        String album = cancion.getAlbum().getNombre();
        String imagen = cancion.getTag("caratula");

        if (imagen == null) {
            imagen = getClass().getResource("/images/CDArt.jpg").toString();
        } else if (imagen.equals("Desconocido")) {
            imagen = getClass().getResource("/images/CDArt.jpg").toString();
        }
        if ((artista.equals("Desconocido")) && (titulo.equals("Desconocido")) && (album.equals("Desconocido"))) {
            songLabel.setText(String.format("<p align:center>%s", cancion.getRuta()));
        } else {
            songLabel.setText(String.format("<table cellpadding='5' width='260' height='100' border='0'><tr align='center'>"
                    + "<td style='width:100px text-align:right;'><img width='70' height='70' src='%s'></td>"
                    + "<td style='width:160px;text-align:left;'><b>%s</b><br>"
                    + "<span style='font-size: 12pt'>%s<br>"
                    + "<span style='font-size: 10pt'><i>%s</i></span>"
                    + "</td></tr></table>", imagen, artista, album, titulo));
        }
        tiempoLabel.setText("00:00");
    }

    /**
     * Actualiza la cancion editada por EditorTags en la lista de reproduccion y en la biblioteca
     * @param cancionOld
     * @param cancionNew
     */
    public void actualizaInfoCancion(Cancion cancionOld, Cancion cancionNew) {
        Cancion cancionRep = player.getCancionPlayer();
        if (cancionRep != null) {
            boolean iguales = cancionNew.equals(player.getCancionPlayer());
            if (iguales) {
                pintarInfoCancion(cancionNew);
            }
        }
        for (int i = 0; i < songListModel.size(); i++) {
            Cancion cancionAux = (Cancion) songListModel.get(i);
            if (cancionAux.equals(cancionNew)) {
                songListModel.setElementAt(cancionNew, i);
            }
        }
    }

    /**
     * Metodo que devuelve un string formateado para pintar la info de la cancion en la lista de reproduccion
     * @param cancion
     * @param formato
     * @param numeroCancion
     * @return
     */
    public String infoCancionParaLista(Cancion cancion, String formato, int numeroCancion) {
        String tiempo = "";
        String artista = "Desconocido";
        String titulo = "Desconocido";
        if (cancion.getTag("duracion").equals("Desconocido")) {
            tiempo = "??:??";
        } else {
            tiempo = formatTime(Double.parseDouble(cancion.getTag("duracion")));
        }
        if (cancion.getArtista() != null && !cancion.getArtista().getNombre().equals("Desconocido")) {
            artista = cancion.getArtista().getNombre();
        }
        if (cancion.getTitulo() != null && !cancion.getTitulo().equals("Desconocido")) {
            titulo = cancion.getTitulo();
        }
        int numCeros = String.valueOf(lista.tamanio()).length() - String.valueOf(numeroCancion).length();
        String numero = "";
        for (int i = 0; i < numCeros; i++) {
            numero += "0";
        }
        numero += numeroCancion;
        return String.format("<html><body><table width='%d' %s height='5' border='0'>"
                + "<tr><td width='%d' padding-right:'1px'>%s. %s - %s</td><td align='right' width='%d'>%s</td>"
                + "</tr></table></body></html>", songListArea.getSize().width - 10, formato, songListArea.getSize().width - 60, numero, artista, titulo, 30, tiempo);
    }

    /**
     * Clase que da formato a las celdas de la songListArea
     */
    class HtmlRenderer extends JTextPane implements ListCellRenderer {

        public HtmlRenderer() {
            super();
            this.setContentType("text/html");
        }

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            String seleccionadaFormat = "";
            if ((Cancion) value == player.getCancionPlayer()) {
                seleccionadaFormat = "color='#4488aa'";
            }
            if (isSelected) {
                setForeground(list.getSelectionForeground());
                setBackground(list.getSelectionBackground());
            } else {
                setForeground(list.getForeground());
                setBackground(list.getBackground());
            }
            setText(infoCancionParaLista((Cancion) value, seleccionadaFormat, index + 1));
            return (this);
        }
    }

    /**
     * Método que borra los datos de la canción del player
     */
    public void limpiarInfoCancion() {
        String imagen = getClass().getResource("/images/dhmo.png").toString();
        songLabel.setText(String.format("<table cellpadding='5' width='260' height='100' border='0'><tr align='center'>"
                + "<td style='width:100px text-align:right;'><img width='70' height='70' src='%s'></td>"
                + "<td style='width:160px;text-align:left;'><b>%s</b><br>"
                + "<span style='font-size: 12pt'>%s<br>"
                + "<span style='font-size: 10pt'><i>%s</i></span>"
                + "</td></tr></table>", imagen, "DHMO", "MP3 Player", "\"que pináculo!\""));
        tiempoLabel.setText("00:00");
    }

    /**
     * Formatea un double a DD:HH:MM:SS.
     * @param t
     * @return String
     */
    private String formatTime(Double t) {
        int dias, horas, minutos, segundos;
        dias = (int) (t / 24) / 3600;
        horas = (int) (t / 3600);
        minutos = (int) (t / 60);
        segundos = (int) (t % 60);
        String tiempo = "";
        if (dias > 0) {
            tiempo += String.format("%d dias %d:%02d:%02d", dias, horas, minutos, segundos);
        } else if (horas > 0) {
            tiempo += String.format("%d:%02d:%02d", horas, minutos, segundos);
        } else {
            tiempo += String.format("%02d:%02d", minutos, segundos);
        }
        return tiempo;
    }

    /**
     * Reinicia el progressBar al valor inicial. Si no se encuentra duracion, convierte el progressbar a indeterminate.
     */
    public void reiniciaProgressBar() {
        progressBar.setValue(0);
        valorBarraProgreso = 0;
        tiempoCancionActual = 0;
        if (player.getCancionPlayer() != null) {
            if (player.getCancionPlayer().getTag("duracion").equals("Desconocido")) {
                tiempoLabel.setText("00:00");
            } else {
                progressBar.setMaximum(Integer.valueOf(player.getCancionPlayer().getTamanio()));
            }
        }
    }

    /**
     * Actualiza la barra de progreso a valor
     * @param valor
     */
    public void actualizaBarraProgreso(int valor) {
        valorBarraProgreso = valor;
    }

    /**
     * Devuelve la lista de reproduccion
     * @return ListaReproduccion lista
     */
    public ListaReproduccion getLista() {
        return this.lista;
    }

    /**
     * Devuelve el songListArea
     * @return songListArea
     */
    public JList getSongListArea() {
        return this.songListArea;
    }

    /**
     * Avanza a la siguiente cancion
     */
    public void siguienteCancion() {
        /*
         * Si está activado repeatOne repetimos la cancionActual, sino la siguiente
         */
        if (estadoRepetir == 1) {
            Cancion cancion = lista.cancionActual();
            songListArea.ensureIndexIsVisible(songListModel.indexOf(cancion));
            songListArea.repaint();
            if (cancion != null) {
                player.stop();
                timer.stop();
                timer.restart();
                pintarInfoCancion(lista.cancionActual());
                player.play(cancion);
                reiniciaProgressBar();
                timer.start();
            } else {
                timer.stop();
                player.stop();
                reiniciaProgressBar();
                limpiarInfoCancion();
            }
        } else {
            nextButtonActionPerformed(null);
        }
    }
}
